﻿/*************************************************************************************
 * 文 件 名:   IHK_LoginRegisterSystem
 * 
 * 描    述:   Unity客户端 与 NodeJsServer服务器端通信功能模块
 *            1.NodeJs 服务器端测试代码在工程根目录下(NodeJs_Server文件夹)
 *            2.NodeJs 服务器端数据存储目前使用的Json，可拓展为MySQL等数据库
 *            3.服务器地址和路由配置文件在StreamingAssets文件夹下
 *            4.Unity客户端分为普通用户和管理员两种类型
 *            5.目前已有功能如下：用户登录、新用户注册、请求用户列表、管理用户列表（删除用户）
 * 
 * 版    本：  V1.0
 * 创 建 者：  京产肠饭
 * 创建时间：  2022/5/14
 * 链   接：  https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using QFramework;

namespace HKTools
{
    /// <summary>
    /// 用户登陆时，输入信息的结构
    /// </summary>
    public class LoginInfo
    {
        public LoginInfo(string username, string password, string accountType)
        {
            this.Username = username;
            this.Password = password;
            this.AccountType = accountType;
        }

        public string Username { get; private set; }
        public string Password { get; private set; }
        public string AccountType { get; private set; }
    }

    /// <summary>
    /// 用户注册时，输入信息的结构
    /// </summary>
    public class RegisterInfo
    {
        public RegisterInfo(string username, string password, string realName)
        {
            this.Username = username;
            this.Password = password;
            this.RealName = realName;
        }

        public string Username { get; private set; }
        public string Password { get; private set; }
        public string RealName { get; private set; }
    }

    public interface IHK_LoginRegisterSystem : ISystem
    {
        /// <summary>
        /// 与 NodeJsServer 服务器通信，请求用户登录的接口（供管理端、用户端使用）
        /// </summary>
        /// <param name="loginInfo">用户登陆时的输入信息</param>
        /// <param name="callback">登陆是否成功的回调函数</param>
        void PostLoginMsg(LoginInfo loginInfo, Action<bool> callback);

        /// <summary>
        /// 与 NodeJsServer 服务器通信，请求用户注册的接口（供用户端使用）
        /// </summary>
        /// <param name="registerInfo">用户注册时的输入信息</param>
        /// <param name="callback">注册是否成功的回调函数</param>
        void PostRegisterMsg(RegisterInfo registerInfo, Action<bool> callback);

        /// <summary>
        /// 与 NodeJsServer 服务器通信，请求用户列表的接口（供管理端使用）
        /// </summary>
        /// <param name="callback">获取用户列表的回调</param>
        void GetUserList(Action<string> callback);

        /// <summary>
        /// 与 NodeJsServer 服务器通信，请求删除指定用户（供管理端使用）
        /// </summary>
        /// <param name="username">指定的用户名</param>
        void PostDeleAppointUser(string username);
    }

    [Serializable]
    public class ServerConfig
    {
        // 服务器的URL
        public string serverURL;
        // 请求登录的路由URL
        public string loginRouter;
        // 请求注册的路由URL
        public string registerRouter;
        // 请求用户列表的路由URL
        public string userListRouter;
        // 删除指定用户的路由URL
        public string deleAppointUserRouter;
    }

    public class HK_LoginRegisterSystem : AbstractSystem, IHK_LoginRegisterSystem
    {
        // 服务器端配置文件
        ServerConfig config;

        // 登陆注册使用的MonoBehavirour工具脚本
        LoginRegister loginRegister;

        protected override void OnInit()
        {
            // 该模块初始化时，实例化一个LoginRegister工具脚本对象
            if (loginRegister == null)
                loginRegister = new GameObject().AddComponent<LoginRegister>();

            TextAsset textAsset = Resources.Load<TextAsset>("HK_LoginRegisterConfig");

            config = JsonUtility.FromJson<ServerConfig>(textAsset.text);
        }

        /// <summary>
        /// 向服务器端发送登录信息
        /// </summary>
        public void PostLoginMsg(LoginInfo loginInfo, Action<bool> callback)
        {
            string url = config.serverURL + config.loginRouter;

            WWWForm form = new WWWForm();
            form.AddField("username", loginInfo.Username);
            form.AddField("password", loginInfo.Password);
            form.AddField("accountType", loginInfo.AccountType);

            loginRegister.PostLoginMsg(url, form, callback);
        }

        /// <summary>
        /// 向服务器发送注册信息
        /// </summary>
        public void PostRegisterMsg(RegisterInfo registerInfo, Action<bool> callback)
        {
            string url = config.serverURL + config.registerRouter;

            WWWForm form = new WWWForm();
            form.AddField("username", registerInfo.Username);
            form.AddField("password", registerInfo.Password);
            form.AddField("realName", registerInfo.RealName);

            loginRegister.PostRegisterMsg(url, form, callback);
        }

        /// <summary>
        /// 与 NodeJsServer 服务器通信，请求用户列表的接口（供管理端使用）
        /// </summary>
        public void GetUserList(Action<string> callback)
        {
            string url = config.serverURL + config.userListRouter;

            loginRegister.GetUserList(url, callback);
        }

        /// <summary>
        /// 与 NodeJsServer 服务器通信，请求删除指定用户（供管理端使用）
        /// </summary>
        public void PostDeleAppointUser(string username)
        {
            string url = config.serverURL + config.deleAppointUserRouter;

            WWWForm form = new WWWForm();
            form.AddField("username", username);

            loginRegister.PostDeleAppointUser(url, form);
        }
    }

    /// <summary>
    /// 登陆注册使用的MonoBehavirour工具脚本
    /// </summary>
    public class LoginRegister : MonoBehaviour
    {
        public void PostLoginMsg(string url, WWWForm form, Action<bool> callback)
        {
            StartCoroutine(LoginAndRegister_IE(url, form, callback));
        }

        public void PostRegisterMsg(string url, WWWForm form, Action<bool> callback)
        {
            StartCoroutine(LoginAndRegister_IE(url, form, callback));
        }

        public void GetUserList(string url, Action<string> callback)
        {
            StartCoroutine(GetUserList_IE(url, callback));
        }

        public void PostDeleAppointUser(string url, WWWForm form)
        {
            StartCoroutine(PostDeleAppointUser_IE(url, form));
        }

        // 登陆注册的 Post 请求
        IEnumerator LoginAndRegister_IE(string url, WWWForm form, Action<bool> callback)
        {
            using (UnityWebRequest request = UnityWebRequest.Post(url, form))
            {
                yield return request.SendWebRequest();

                if (!string.IsNullOrEmpty(request.error))
                    Debug.LogError(request.error);

                if (request.downloadHandler.text == "true")
                    callback(true);
                else
                    callback(false);
            }
        }

        // 获取用户列表的 Get 请求
        IEnumerator GetUserList_IE(string url, Action<string> callback)
        {
            using (UnityWebRequest request = UnityWebRequest.Get(url))
            {
                yield return request.SendWebRequest();

                if (!string.IsNullOrEmpty(request.error))
                    Debug.LogError(request.error);

                callback(request.downloadHandler.text);
            }
        }

        // 删除指定用户 Post 请求
        IEnumerator PostDeleAppointUser_IE(string url, WWWForm form)
        {
            using (UnityWebRequest request = UnityWebRequest.Post(url, form))
            {
                yield return request.SendWebRequest();

                if (!string.IsNullOrEmpty(request.error))
                    Debug.LogError(request.error);
            }
        }
    }
}